﻿#pragma once

#include "common.h"
#include "graphics.h"
#include <vector>

namespace anip
{
	class Sequence : public GraphicObject, public Serializable<Sequence>
	{
		serializable_id(Sequence, 0);

	public:
		class Element
		{
			friend class Sequence;

		private:
			Sequence* _parent = nullptr;
			int _position, _row;
			int _cutStart, _duration;
			TemporalTiling _temporalTile;

		public:
			FrameGroup& frameGroup;

			Element(FrameGroup& fg, int pos, int duration, int row = 0, int start = 0, 
				TemporalTiling tile = TemporalTiling::None) :
				frameGroup(fg), _position(pos), _row(row), _duration(duration),
				_cutStart(start), _temporalTile(tile)
			{}

			int position() const { return _position; }
			int row() const { return _row; }
			int cutStart() const { return _cutStart; }
			int duration() const { return _duration; }
			TemporalTiling temporalTiling() const { return _temporalTile; }

			void setPosition(int p)
			{
				assert(p >= 0);
				_position = p;
				_parent->_applyChanges(*this);
			}

			void setRow(int r)
			{
				_row = r;
				_parent->_applyChanges(*this);
			}

			void setCutStart(int c)
			{
				_cutStart = c;
				_parent->_applyChanges(*this);
			}

			void setDuration(int d)
			{
				assert(d > 0);
				_duration = d;
				_parent->_applyChanges(*this);
			}

			void setTemporalTiling(TemporalTiling t)
			{
				_temporalTile = t;
				_parent->_applyChanges(*this);
			}
		};

	private:
		class Renderer;

		float _frameRate = 24;
		int _duration = 0;
		std::vector<Element> _elements;

		void _applyChanges(Element& e);

	public:
		Sequence(const Sequence& obj) = delete;
		Sequence(float frameRate = 24) : _frameRate(frameRate) {}
		Sequence(float frameRate, std::initializer_list<Element> groups) :
			_frameRate(frameRate)
		{
			add(groups, 0);
		}

		GraphicsRenderer* createRenderer() override;
		int length() const override { return _duration; }
		
		const std::vector<Element>& content() const { return _elements; }

		float frameRate() const { return _frameRate; }

		kvec2 position = vec2{ 0, 0 };
		kfloat zoom = 1;

		void add(Element group);
		void add(std::initializer_list<Element> groups, int offset = 0);
	};
}